﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using LLClient.ClientServiceRef;
using LLClient.ServerProxy;
using LLClient.SaveAndLoad;
using Microsoft.Win32;

namespace LLClient.Battle
{
    /// <summary>
    /// Interaction logic for BattleWindow.xaml
    /// </summary>
    public partial class BattleWindow : Window
    {
        #region Constant Values
        private const int N_LINES = 10;
        private const int BLOCK_SIZE = 30;
        private const int FIELD_SIZE = 50;
        private const int PATROL = 1;
        private const int SUBMARINE = 2;
        private const int DESTROYER = 3;
        private const int BATTLESHIP = 4;
        private const int CARRIER = 5;
        #endregion

        private bool isYourMove;
        private bool isPaused;
        private bool[] hasBeenShot;
        private Dictionary<int, int> myShips;
        private Proxy _proxy = Proxy.GetInstance();
        private bool _eventRegistered = false;
        private Client _currentClient = Proxy.GetInstance().CurrentClient;
        private Client _enemyClient;
        Turn lastTurn;
        private LLFile savedScenario;

        public Client CurrentClient
        {
            get { return _currentClient; }
            set { _currentClient = value; }
        }

        public BattleWindow()
        {
            InitializeComponent();
            drawInitGrid();
        }

        public BattleWindow(bool move, System.Windows.Controls.Grid prevGrid, Dictionary<int, int> ships)
        {
            InitializeComponent();
            
            isYourMove = move;
            if (isYourMove)
                infoLabel.Content = "Your move";
            else
                infoLabel.Content = "Enemy's move";
            isPaused = false;

            hasBeenShot = new bool[100];

            List<UIElement> temp = new List<UIElement>();
            foreach (UIElement uie in prevGrid.Children)
                temp.Add(uie);

            foreach (UIElement uie in temp)
            {
                prevGrid.Children.Remove(uie);
                gridYours.Children.Add(uie);
            }

            myShips = ships;
            drawInitGrid();

            if (!_eventRegistered)
            {
                if (_proxy != null)
                {
                    _proxy.ProxyCallbackEvent += _proxy_ProxyCallbackEvent;
                    _proxy.ProxyBattleCallbackEvent += _proxy_ProxyBattleCallbackEvent;
                }

                _eventRegistered = true;
            }

            this.Title = "Battle Window - " + CurrentClient.Username;
            this.Closing += WindowClosing;

            savedScenario = new LLFile();
            _proxy.ProxyService.GetEnemyClientAndMe();
        }

        void _proxy_ProxyCallbackEvent(object sender, ProxyCallbackEventArgs e)
        {
            Dispatcher.BeginInvoke(new Action(() =>
            {
                if (e.Sender != null)
                {
                    switch (e.CallbackType)
                    {
                        case CallbackType.ReceiveWhisper:
                            chatBox.Text += e.Sender.Username + ": " + e.Message.Content;
                            break;
                        case CallbackType.ShotResult:
                            string position = "";
                            position += (char)(lastTurn.Target_tile / 10 + 65);
                            position += (lastTurn.Target_tile % 10 + 1).ToString();
                            logTextBox.Text += e.Message.Content + " (" + position +")\n";
                            drawMyShot(e.Message.Respond);
                            break;
                        case CallbackType.ReceiveEnemyClient:
                            _enemyClient = e.Message.Sender;
                            CurrentClient = e.Sender;
                            savedScenario.Captain1Name = CurrentClient.CaptainName;
                            savedScenario.Captain2Name = _enemyClient.CaptainName;
                            savedScenario.Field1 = e.Player1Ships;
                            savedScenario.Field2 = e.Player2Ships;
                            break;
                        case CallbackType.BattleOver:
                            logTextBox.Text += e.Message.Content + "\n";
                            infoLabel.Content = e.Message.Content;
                            Portal.MainMenu mmWindow =  new Portal.MainMenu();
                            if (e.Message.Respond)
                            {
                                MessageBox.Show(e.Message.Content, CurrentClient.Username + ": Congratulation", MessageBoxButton.OK, MessageBoxImage.Information);
                            }
                            else
                            {
                                MessageBox.Show(e.Message.Content, CurrentClient.Username + ": You are defeated", MessageBoxButton.OK, MessageBoxImage.Information);
                            }
                            SaveToFile();
                            mmWindow.Show();
                            this.Close();
                            break;
                    }
                }
            }));
        }

        void _proxy_ProxyBattleCallbackEvent(object sender, ProxyCallbackBattleArgs e)
        {
            Dispatcher.BeginInvoke(new Action(() =>
            {
                if (e.Sender != null)
                {
                    switch (e.CallbackType)
                    {
                        case CallbackType.PauseBattle:
                            isPaused = true;
                            infoLabel.Content = "Game is paused";
                            pauseButton.IsEnabled = false;
                            break;
                        case CallbackType.ResumeBattle:
                            isPaused = false;
                            pauseButton.IsEnabled = true;
                            if (isYourMove)
                                setYourTurn();
                            else
                                infoLabel.Content = "Enemy's Move";
                            break;
                        case CallbackType.GotShot:
                            DrawShot(e.Turn);
                            TurnSerialized t = new TurnSerialized(e.Turn);
                            savedScenario.Turns.Add(t);
                            setYourTurn();
                            break;
                    }
                }
            }));
        }

        private void surrenderButton_Click(object sender, RoutedEventArgs e)
        {
            Turn t = new Turn();
            t.Surrender = true;
            // need some additional infos..
            _proxy.ProxyService.Shot(t);
        }

        private void sendButton_Click(object sender, RoutedEventArgs e)
        {
            string message = inputTextBox.Text;
            if (message != null & message != "")
            {
                _proxy.ProxyService.SendWhisper(_enemyClient.Username, message);
                chatBox.Text += "You: " + message;
            }
        }

        private void gridEnemys_MouseMove(object sender, MouseEventArgs e)
        {
            if (isYourMove)
            {

            }
        }

        private void gridEnemys_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (isYourMove && !isPaused)
            {
                Point p = e.GetPosition(gridEnemys);
                int index = (((int)p.X / 30) % 10) + ((int)p.Y / 30 * 10);

                if (!hasBeenShot[index])
                {
                    lastTurn = new Turn();
                    lastTurn.Cpt_name = CurrentClient.CaptainName;
                    lastTurn.Shot = true;
                    lastTurn.Target_tile = index;
                    lastTurn.Surrender = false;
                    hasBeenShot[index] = true;
                    _proxy.ProxyService.Shot(lastTurn);
                    savedScenario.Turns.Add(new TurnSerialized(lastTurn));

                    isYourMove = false;
                    infoLabel.Content = "Enemy's Move";
                }
                else // you have shot this field
                {
                    MessageBox.Show("You have shot this field", CurrentClient.Username + ": Error", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                }
            }
            else if (isPaused)
            {
                MessageBox.Show("Game is paused", CurrentClient.Username + ": Information", MessageBoxButton.OK, MessageBoxImage.Information);
            }
        }

        private void gridEnemys_MouseLeave(object sender, MouseEventArgs e)
        {
            if (isYourMove)
            {

            }
        }

        private void DrawShot(Turn turn)
        {
            if (myShips.ContainsKey(turn.Target_tile))
            {
                FlagHitControl flag = new FlagHitControl();
                int x = (turn.Target_tile % 10) * 30;
                int y = (turn.Target_tile / 10) * 30;
                flag.Margin = new Thickness(x, y, 0, 0);

                gridYours.Children.Add(flag);
            }
            else
            {
                FlagMissedControl flag = new FlagMissedControl();
                int x = (turn.Target_tile % 10) * 30;
                int y = (turn.Target_tile / 10) * 30;
                flag.Margin = new Thickness(x, y, 0, 0);

                gridYours.Children.Add(flag);
            }
        }

        private void drawMyShot(bool result)
        {
            if (lastTurn != null)
            {
                if (result)
                {
                    FlagHitControl flag = new FlagHitControl();
                    int x = (lastTurn.Target_tile % 10) * 30;
                    int y = (lastTurn.Target_tile / 10) * 30;
                    flag.Margin = new Thickness(x, y, 0, 0);

                    gridEnemys.Children.Add(flag);
                }
                else
                {
                    FlagMissedControl flag = new FlagMissedControl();
                    int x = (lastTurn.Target_tile % 10) * 30;
                    int y = (lastTurn.Target_tile / 10) * 30;
                    flag.Margin = new Thickness(x, y, 0, 0);

                    gridEnemys.Children.Add(flag);
                }
            }
        }

        private void setYourTurn()
        {
            isYourMove = true;
            infoLabel.Content = "Your Move";
        }

        private void drawInitGrid()
        {
            // draw vertical lines
            for (int i = 1; i < N_LINES; i++)
            {
                Line line = new Line();

                line.Stroke = Brushes.Black;
                line.Fill = Brushes.Black;
                line.StrokeThickness = 1;
                line.X1 = i * BLOCK_SIZE;
                line.X2 = line.X1;

                line.Y1 = 0;
                line.Y2 = gridEnemys.Height;

                gridEnemys.Children.Add(line);
            }

            // draw horizontal lines
            for (int i = 1; i < N_LINES; i++)
            {
                Line line = new Line();

                line.Stroke = Brushes.Black;
                line.Fill = Brushes.Black;
                line.StrokeThickness = 1;
                line.Y1 = i * BLOCK_SIZE;
                line.Y2 = line.Y1;

                line.X1 = 0;
                line.X2 = gridEnemys.Width;

                gridEnemys.Children.Add(line);
            }
        }

        public void WindowClosing(object sender, EventArgs e)
        {
            if (_proxy != null)
            {
                _proxy.ProxyCallbackEvent -= _proxy_ProxyCallbackEvent;
                _proxy.ProxyBattleCallbackEvent -= _proxy_ProxyBattleCallbackEvent;
            }
            _eventRegistered = false;
        }

        private void SaveToFile()
        {
            SaveFileDialog saveDialog = new SaveFileDialog();

            // Show save file dialog box
            Nullable<bool> result = saveDialog.ShowDialog();

            // Process save file dialog box results
            if (result == true)
            {
                // Save document
                string filename = saveDialog.FileName;
                Serializer.SerializeLLFile(filename, savedScenario);
            }//Serializer.SerializeLLFile("tryone-"+CurrentClient.Username+".obj", savedScenario);
        }

        private void pauseButton_Click(object sender, RoutedEventArgs e)
        {
            if (!isPaused)
            {
                _proxy.ProxyService.PauseBattle();
                isPaused = true;
                pauseButton.Content = "Resume";
                infoLabel.Content = "Game is Paused";
            }
            else
            {
                _proxy.ProxyService.ResumeBattle();
                isPaused = false;
                if (isYourMove)
                    setYourTurn();
                else
                    infoLabel.Content = "Enemy's Move";
                pauseButton.Content = "Pause";
            }
        }
    }
}
